import dayjs from "dayjs";
import JSONBig from "json-bigint";
// import BigNumber from "bignumber.js";
export const showToast = (message, icon, duration) => {
  uni.showToast({
    title: message,
    icon: `${icon || "none"}`,
    duration: 2000 || duration,
  });
};

//数组去重
export const unique = (arr, key) => {
  if (key) {
    const seen = new Set();
    return arr?.filter((item) => {
      if (seen.has(item[key])) return false;
      seen.add(item[key]);
      return true;
    });
  } else {
    return [...new Set(arr)];
  }
};

// 时间格式化方法
export const formatTime = (time, format = "YYYY-MM-DD HH:mm:ss") => {
  if (!time) return "";
  if (time && Number(time) !== 0) {
    // 取秒的时间戳来格式化(daysjs默认以毫秒时间戳为基准来处理，如需以秒的时间戳为基准则使用 dayjs.unix(秒的时间戳) )
    return dayjs.unix(Number(time)).format(format);
  } else {
    return "";
  }
};

// 相对时间格式化（多久前）
export const formatRelativeTime = (time) => {
  if (!time) return "";

  const now = new Date();
  const target = new Date(time);
  const diff = now - target;

  const minute = 60 * 1000;
  const hour = 60 * minute;
  const day = 24 * hour;
  const month = 30 * day;
  const year = 365 * day;

  if (diff < minute) return "刚刚";
  if (diff < hour) return `${Math.floor(diff / minute)}分钟前`;
  if (diff < day) return `${Math.floor(diff / hour)}小时前`;
  if (diff < month) return `${Math.floor(diff / day)}天前`;
  if (diff < year) return `${Math.floor(diff / month)}个月前`;
  return `${Math.floor(diff / year)}年前`;
};

// 判断银行卡号真实性
export const checkBankcard = (cardNo) => {
  let cardNoArr = [];
  for (let i = 0; i < cardNo.length; i++) {
    cardNoArr[i] = Number(cardNo.charAt(i));
  }
  for (let i = cardNoArr.length - 2; i >= 0; i -= 2) {
    cardNoArr[i] <<= 1;
    cardNoArr[i] =
      Math.trunc(cardNoArr[i] / 10) + Math.trunc(cardNoArr[i] % 10);
  }
  let sum = 0;
  for (let aCardNoArr in cardNoArr) {
    sum += cardNoArr[aCardNoArr];
  }
  return sum % 10 === 0;
};

/**
 * 格式化金额（支持大整数和小数，保证精度）
 * @param {string|number} amount - 金额
 * @param {number} precision - 保留的小数位
 * @param {"auto"|"string"|"number"} returnType - 返回类型
 */
export const formatAmount = (amount, precision = 2, returnType = "auto") => {
  if (
    amount === null ||
    amount === undefined ||
    amount === "" ||
    isNaN(amount)
  ) {
    return amount;
  }

  const isStringInput = typeof amount === "string";
  let str = String(amount);

  // 统一成字符串小数，避免浮点数运算
  if (!str.includes(".")) {
    str += ".0";
  }

  // 使用 BigInt 来处理整数部分，但保留小数
  const [intPart, decPart] = str.split(".");

  // 金额除以 1_000_000（用字符串实现）
  const divisor = 1_000_000;

  // 用浮点数做缩放，但用 toFixed 控制精度
  let result = (Number(str) / divisor).toFixed(precision);

  // ===== 返回类型控制 =====
  if (returnType === "string" || isStringInput) {
    return result;
  } else if (
    returnType === "number" ||
    (!isStringInput && returnType === "auto")
  ) {
    return Number(result);
  }
};

// 获取页面参数
export const getPageParams = () => {
  const pages = getCurrentPages();
  const currentPage = pages[pages.length - 1];
  const options = currentPage.options || {};
  return options;
};

// 主题色
export const theme = {
  primary: "#2979ff",
  primary_hover: "#409eff",
  success: "#4caf50",
  warning: "#ff9800",
  error: "#f44336",
  text: "#333",
  bg: "#f8f8f8",
};

// 格式化大整数金额，保持精度
export const formatBigIntAmount = (amount) => {
  if (!amount) return "0";
  return JSONBig({ storeAsString: true }).parse(amount);
};

// 格式化大整数
export const safeStringify = (obj) => {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === "object" && value !== null) {
      if (seen.has(value)) {
        return "[Circular]";
      }
      seen.add(value);
    }

    if (typeof value === "bigint") {
      return value.toString();
    }

    if (typeof value === "number") {
      if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {
        return value.toString();
      }
      if (!isFinite(value)) {
        return value.toString();
      }
      if (isNaN(value)) {
        return "null";
      }
    }

    return value;
  });
};

/**
 * 数字格式化成科学计数法
 * @param {number|string} number - 要格式化的数字
 * @param {number} precision - 精度，默认2位小数
 * @param {object} options - 配置选项
 * @param {boolean} options.forceExponential - 是否强制使用科学计数法，默认false（自动判断）
 * @param {number} options.threshold - 自动使用科学计数法的阈值，默认1000000（100万）
 * @returns {string} 格式化后的字符串
 */
export const formatToScientific = (number, precision = 2, options = {}) => {
  const { forceExponential = false, threshold = 1000000 } = options;

  // 输入验证
  if (number === null || number === undefined || number === "") {
    return "0";
  }

  // 转换为数字
  const num = Number(number);

  // 处理特殊值
  if (isNaN(num)) {
    return "0";
  }

  if (!isFinite(num)) {
    return num.toString();
  }

  if (num === 0) {
    return "0";
  }

  // 判断是否需要使用科学计数法
  const absNum = Math.abs(num);
  const shouldUseExponential =
    forceExponential || absNum >= threshold || absNum < 0.001;

  if (shouldUseExponential) {
    // 使用科学计数法
    return num.toExponential(precision);
  } else {
    // 使用常规格式，保留指定精度
    return num.toFixed(precision).replace(/\.?0+$/, "");
  }
};

/**
 * 给数字添加千位分隔符
 * @param {number|string|bigint} input - 要格式化的数字
 * @param {Object} [opts]
 * @param {string} [opts.thousandSep=','] - 千分位分隔符
 * @param {string} [opts.decimalSep='.']  - 小数点符号
 * @param {number} [opts.decimals]        - 固定保留的小数位数 (四舍五入)
 * @returns {string}
 */
function formatWithThousands(num, opts = {}) {
  const { thousandSep = ",", decimalSep = ".", decimals = undefined } = opts;

  if (num === null || num === undefined) return "";

  let str = String(num).replace(/[, ]/g, ""); // 去掉可能已有的分隔符

  // 判断正负号
  let sign = "";
  if (str[0] === "-" || str[0] === "+") {
    sign = str[0] === "-" ? "-" : "";
    str = str.slice(1);
  }

  // BigInt 转换
  if (typeof num === "bigint") {
    str = num.toString();
  }

  // 拆分整数 / 小数部分
  let [intPart, fracPart = ""] = str.split(".");

  // 小数位处理
  if (decimals != null) {
    const num = Number(`${sign}${intPart}.${fracPart}`);
    if (Number.isFinite(num)) {
      str = num.toFixed(decimals);
      [intPart, fracPart = ""] = str.split(".");
    }
  }

  // 整数部分加千分位
  const reg = /\B(?=(\d{3})+(?!\d))/g;
  intPart = intPart.replace(reg, thousandSep);

  // 返回
  return sign + (fracPart ? intPart + decimalSep + fracPart : intPart);
}

/**
 * 处理API错误，包括请求取消的情况
 * @param {Error} error - 错误对象
 * @param {Object} options - 配置选项
 * @param {boolean} options.showToast - 是否显示错误提示，默认为true
 * @param {boolean} options.ignoreCancel - 是否忽略取消请求的错误，默认为true
 * @returns {Object} 处理后的错误对象
 */
export const handleApiError = (error, options = {}) => {
  const { showToast: shouldShowToast = true, ignoreCancel = true } = options;

  // 如果是取消的请求且配置为忽略，则直接返回
  if (ignoreCancel && error?.code === "ERR_CANCELED") {
    console.log("请求已取消", error?.message);
    return {
      success: false,
      canceled: true,
      message: "请求已取消",
    };
  }

  // 处理其他类型的错误
  const errorMessage = error?.desc || error?.message || "请求失败";

  // 如果配置为显示错误提示，则显示
  if (shouldShowToast) {
    showToast(errorMessage);
  }

  return {
    success: false,
    canceled: false,
    message: errorMessage,
    error,
  };
};

// ---------------- 使用示例 ----------------
// console.log(formatWithThousands(1234567.89));               // "1,234,567.89"
// console.log(formatWithThousands("1000000000"));             // "1,000,000,000"
// console.log(formatWithThousands(1234567.89, { thousandSep: " " })); // "1 234 567.89"
// console.log(formatWithThousands(1234567.89, { decimals: 2 }));      // "1,234,567.89"
// console.log(formatWithThousands(1234567.8, { decimals: 4 }));       // "1,234,567.8000"
// console.log(formatWithThousands(1234567n));                 // "1,234,567"
// console.log(formatWithThousands(-9876543.21));              // "-9,876,543.21"
// console.log(formatWithThousands(1234567.89, { decimalSep: "," }));  // "1,234,567,89"

/**
 * 深拷贝数组
 * @param arr
 */
const deepArray = (arr) => {
  return arr.map(deepClone);
};

/**
 * 深拷贝Map对象
 * @param object
 */
const deepMapObject = (mapObject) => {
  const mapObj = new Map([...mapObject.entries()]);
  return mapObj;
};

/**
 * 深拷贝对象
 * @param object
 */
const deepObject = (object) => {
  const keys = Object.keys(object);
  const result = {};
  keys.forEach((item) => {
    result[item] = deepClone(object[item]);
  });

  return result;
};

/**
 * 深拷贝
 * @param data
 */
export const deepClone = (data) => {
  if (!data) {
    return data;
  }
  if (typeof data !== "object") {
    return data;
  }
  if (Array.isArray(data)) {
    return deepArray(data);
  }
  if (data instanceof Map) {
    return deepMapObject(data);
  }
  return deepObject(data);
};
